//
//  AbilityChanged.m
//  This file is part of D&D Manager
//
//  Created by Matthew Hutton on 25/02/2007.
//
//
//D&D Manager, a D&D Character and battle management program.
//Copyright (C) 2007, Matthew Hutton
//
//This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License along with this program; if not, write to:
//The Free Software Foundation, Inc.,
//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

#import "AbilityChanged.h"
#import "RandomNumbers.h"

@implementation AbilityChanged
+(void)strengthChangedForChar:(NSManagedObject *)obj{
	//update strength value.
	int strBonus;
	if([obj valueForKey:@"strengthBase"]==nil){
		[obj setValue:nil
			   forKey:@"strength"];
		strBonus=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"strengthBase"] intValue]+[[obj valueForKey:@"strengthTemp"] intValue]]
			   forKey:@"strength"];
		strBonus=[self scoreToBonus:[obj valueForKey:@"strength"]];
	}
	//do everything else.

	[obj setValue:[NSNumber numberWithInt:(strBonus+[[obj valueForKey:@"baseAttackBonus"] intValue]+[[obj valueForKey:@"meleeMiscBonus"] intValue])]
		   forKey:@"meleeAttackBonus"];
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==0){//strength
			[skill setValue:[NSNumber numberWithInt:(strBonus+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:strBonus]
					 forKey:@"abilityBonus"];
			
		}
	}
}
+(void)dexterityChangedForChar:(NSManagedObject *)obj{
	//update dex value.
	int x;
	if([obj valueForKey:@"dexterityBase"]==nil){
		[obj setValue:nil
			   forKey:@"dexterity"];
		x=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"dexterityBase"] intValue]+[[obj valueForKey:@"dexterityTemp"] intValue]]
			   forKey:@"dexterity"];
		x=[self scoreToBonus:[obj valueForKey:@"dexterity"]];
	}
	//everything else.
	//reflex stuff.
	int rTot=[[obj valueForKey:@"reflexBase"] intValue]+x+[[obj valueForKey:@"reflexMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:rTot]
		   forKey:@"reflexTotal"];
	//now do init stuff
	int initTot=x+[[obj valueForKey:@"initiativeMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:initTot]
		   forKey:@"initiativeBonus"];
	
	//Base Attack Bonus stuff (ranged)
	[obj setValue:[NSNumber numberWithInt:(x+[[obj valueForKey:@"baseAttackBonus"] intValue]+[[obj valueForKey:@"rangedMiscBonus"] intValue])]
		   forKey:@"rangedAttackBonus"];
	//Base Attack Bonus stuff (melee)
	int strBonus=[self scoreToBonus:[obj valueForKey:@"strength"]];
	[obj setValue:[NSNumber numberWithInt:(strBonus+[[obj valueForKey:@"baseAttackBonus"] intValue]+[[obj valueForKey:@"meleeMiscBonus"] intValue])]
		   forKey:@"meleeAttackBonus"];
	//now do AC Stuff.
	int x2=[self dexACBonus:obj];
	//now add up armour class changes.
	int acTot=[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+x2+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	int acTouchVal=x2+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	//adding dex penalty to AC flat as required.
	int dexPen=0;
	if(x2<0){
		dexPen=x2;
	}
	int acFlatVal=dexPen+[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	//check whether default weapon uses a shield or not.
	NSManagedObject *weap=[obj valueForKey:@"defaultWeapon"];
	//now check weapon.
	if([[weap valueForKey:@"withShield"] boolValue]){
		//enable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:acTot]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:acFlatVal]
			   forKey:@"armourClassFlat"];
	}else{
		//disable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:(acTot-[[obj valueForKey:@"armourClassShield"] intValue])]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:(acFlatVal-[[obj valueForKey:@"armourClassShield"] intValue])]
			   forKey:@"armourClassFlat"];
	}
	//nothing to do with the shield.
	[obj setValue:[NSNumber numberWithInt:acTouchVal]
		   forKey:@"armourClassTouch"];
	//set up skills
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==2){//dexterity.
			[skill setValue:[NSNumber numberWithInt:(x+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:x]
					 forKey:@"abilityBonus"];
		}
	}
}
+(void)constitutionChangedForChar:(NSManagedObject *)obj{
	int conBon;
	//update con value.
	if([obj valueForKey:@"constitutionBase"]==nil){
		[obj setValue:nil
			   forKey:@"constitution"];
		conBon=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"constitutionBase"] intValue]+[[obj valueForKey:@"constitutionTemp"] intValue]]
			   forKey:@"constitution"];
		conBon=[self scoreToBonus:[obj valueForKey:@"constitution"]];
	}
	
	//everything else.
	int fTot=[[obj valueForKey:@"fortitudeBase"] intValue]+conBon+[[obj valueForKey:@"fortitudeMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:fTot]
		   forKey:@"fortitudeTotal"];
	[obj setValue:[NSNumber numberWithInt:[self conHPBonus:obj]+[[obj valueForKey:@"baseHP"] intValue]]
		   forKey:@"maxHP"];
	//set up skills
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==4){//constitution.
			[skill setValue:[NSNumber numberWithInt:(conBon+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:conBon]
					 forKey:@"abilityBonus"];
		}
	}
}
+(void)intelligenceChangedForChar:(NSManagedObject *)obj{
	//update int value.
	int intBonus;
	if([obj valueForKey:@"intelligenceBase"]==nil){
		[obj setValue:nil
			   forKey:@"intelligence"];
		intBonus=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"intelligenceBase"] intValue]+[[obj valueForKey:@"intelligenceTemp"] intValue]]
			   forKey:@"intelligence"];
		intBonus=[self scoreToBonus:[obj valueForKey:@"intelligence"]];
	}
	//everything else.
	//set up skill points/level
	int total=intBonus+[[obj valueForKey:@"skillPointsMiscBonus"] intValue]+[[obj valueForKey:@"skillPointsClassScore"] intValue];
	[obj setValue:[NSNumber numberWithInt:total]
		   forKey:@"skillPointsTotal"];
	//set up skills
	NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==1){//intelligence
			[skill setValue:[NSNumber numberWithInt:intBonus+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"]intValue]]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:intBonus]
					 forKey:@"abilityBonus"];
			
		}
	}
}
+(void)wisdomChangedForChar:(NSManagedObject *)obj{
	//update wis value.
	int x;
	if([obj valueForKey:@"wisdomBase"]==nil){
		[obj setValue:nil
			   forKey:@"wisdom"];
		x=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"wisdomBase"] intValue]+[[obj valueForKey:@"wisdomTemp"] intValue]]
			   forKey:@"wisdom"];
		x=[self scoreToBonus:[obj valueForKey:@"wisdom"]];
	}
	//everything else.
	int wTot=[[obj valueForKey:@"willBase"] intValue]+x+[[obj valueForKey:@"willMiscBonus"] intValue];
	[obj setValue:[NSNumber numberWithInt:wTot]
		   forKey:@"willTotal"];
	//set up skills
	NSArray *skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill;
		skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==3){//wisdom.
			[skill setValue:[NSNumber numberWithInt:(x+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"] intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:x]
					 forKey:@"abilityBonus"];
		}
	}	
}
+(void)charismaChangedForChar:(NSManagedObject *)obj{
	//update char value.
	//blah blah
	int chaMod;
	if([obj valueForKey:@"charismaBase"]==nil){
		[obj setValue:nil
			   forKey:@"charisma"];
		chaMod=0;
	}else{
		[obj setValue:[NSNumber numberWithInt:[[obj valueForKey:@"charismaBase"] intValue]+[[obj valueForKey:@"charismaTemp"] intValue]]
			   forKey:@"charisma"];
		chaMod=[self scoreToBonus:[obj valueForKey:@"charisma"]];
	}
	//everything else.
	//turn undead
	[obj setValue:[NSNumber numberWithInt:(3+chaMod+[[obj valueForKey:@"tuMiscBonus"] intValue])]
		   forKey:@"tuTotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuCMiscBonus"] intValue])]
		   forKey:@"tuCtotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuHDMiscBonus"] intValue]+[self turnUndeadCL:obj])]
		   forKey:@"tuHDtotal"];
	//set up skills
	NSArray *skills;
	skills=[[obj valueForKey:@"skills"] allObjects];
	int i;
	for(i=0;i<[skills count];i++){
		NSManagedObject *skill=[skills objectAtIndex:i];
		if([[skill valueForKey:@"ability"] intValue]==5){//charisma
			[skill setValue:[NSNumber numberWithInt:(chaMod+[[skill valueForKey:@"rank"] intValue]+[[skill valueForKey:@"miscBonus"] intValue])]
					 forKey:@"total"];
			[skill setValue:[NSNumber numberWithInt:chaMod]
					 forKey:@"abilityBonus"];
			
		}
	}
}
+(void)updateTurnUndeadForChar:(NSManagedObject *)obj{
	int chaMod=[self scoreToBonus:[obj valueForKey:@"charisma"]];
	//NSLog(@"chaMod=%d",chaMod);
	[obj setValue:[NSNumber numberWithInt:(3+chaMod+[[obj valueForKey:@"tuMiscBonus"] intValue])]
		   forKey:@"tuTotal"];
	[obj setValue:[NSNumber numberWithInt:(chaMod+[[obj valueForKey:@"tuCMiscBonus"] intValue])]
		   forKey:@"tuCtotal"];
}
+(int)scoreToBonus:(NSNumber *)score{
	if(score==nil){
		return 0;
	}
    int abilityBonus=[score intValue]-10;
	if(abilityBonus<0){
		abilityBonus--;
	}
	return abilityBonus/2;
}
+(int)conHPBonus:(NSManagedObject *)value{
	//calculate constitution bonus.
	int conBonus=[self scoreToBonus:[value valueForKey:@"constitution"]];
	//multiply by level
	return conBonus*[[value valueForKey:@"level"] intValue];
}
+(int)turnUndeadCL:(NSManagedObject *)value{
	NSString *class1=[value valueForKey:@"charClassName1"];
	NSString *class2=[value valueForKey:@"charClassName2"];
	NSString *class3=[value valueForKey:@"charClassName3"];
	int l1=[[value valueForKey:@"charClassLvl1"] intValue];
	int l2=[[value valueForKey:@"charClassLvl2"] intValue];
	int l3=[[value valueForKey:@"charClassLvl3"] intValue];
	int clericLevel=0;
	if([class1 caseInsensitiveCompare:@"Cleric"]==NSOrderedSame){
		clericLevel=l1;
	}
	if([class2 caseInsensitiveCompare:@"Cleric"]==NSOrderedSame){
		if(l2>clericLevel){
			clericLevel=l2;
		}
	}
	if([class3 caseInsensitiveCompare:@"Cleric"]==NSOrderedSame){
		if(l3>clericLevel){
			clericLevel=l3;
		}
	}
	if([class1 caseInsensitiveCompare:@"Paladin"]==NSOrderedSame){
		if(l1-3>clericLevel){
			clericLevel=l1-3;
		}
	}
	if([class2 caseInsensitiveCompare:@"Paladin"]==NSOrderedSame){
		if(l2-3>clericLevel){
			clericLevel=l2-3;
		}
	}	
	if([class3 caseInsensitiveCompare:@"Paladin"]==NSOrderedSame){
		if(l3-3>clericLevel){
			clericLevel=l3-3;
		}
	}
	return clericLevel;
}
+(int)dexACBonus:(NSManagedObject*)value{
	int dexScore=[self scoreToBonus:[value valueForKey:@"dexterity"]];
	NSString *maxDexBonus=[value valueForKey:@"maxDexBonus"];
	//NSLog(@"maxDexBonus=%@",maxDexBonus);
	if([maxDexBonus isEqualToString:@"none"]){
		
	}else if ([maxDexBonus isEqualToString:@"+8"]){
		if(dexScore>8){
			dexScore=8;
		}
	}else if ([maxDexBonus isEqualToString:@"+7"]){
		if(dexScore>7){
			dexScore=7;
		}
		
	}else if ([maxDexBonus isEqualToString:@"+6"]){
		if(dexScore>6){
			dexScore=6;
		}
	}else if ([maxDexBonus isEqualToString:@"+5"]){
		if(dexScore>5){
			dexScore=5;
		}
	}else if ([maxDexBonus isEqualToString:@"+4"]){
		if(dexScore>4){
			dexScore=4;
		}
	}else if ([maxDexBonus isEqualToString:@"+3"]){
		if(dexScore>3){
			dexScore=3;
		}
	}else if ([maxDexBonus isEqualToString:@"+2"]){
		if(dexScore>2){
			dexScore=2;
		}
	}else if ([maxDexBonus isEqualToString:@"+1"]){
		if(dexScore>1){
			dexScore=1;
		}
	}else if ([maxDexBonus isEqualToString:@"+0"]){
		if(dexScore>0){
			dexScore=0;
		}
	}
	return dexScore;
}
+(int)abilityAttackBonus:(id)value{
	NSManagedObject *obj=[value valueForKey:@"character"];
	int ab;
	if([[value valueForKey:@"weaponType"] intValue]==2){
		ab=[[obj valueForKey:@"rangedAttackBonus"] intValue];
	}else{
		ab=[[obj valueForKey:@"meleeAttackBonus"] intValue];
	}
	//NSLog(@"1, ab=%d",ab);
	//if a monster secondary attacks have -5 penalty to hit.
	if(![[obj valueForKey:@"usesWeapons"] boolValue] && ![[obj valueForKey:@"defaultWeapon"] isEqualTo:value]){
		ab=ab-5;
	}
	//NSLog(@"2, ab=%d",ab);
	//if uses two weapons add main/off penalties as required.
	if([[obj valueForKey:@"usesTwoWeapons"] intValue]){
		if([value isEqualTo:[obj valueForKey:@"defaultWeapon"]]){
			ab=ab+[[obj valueForKey:@"mainHandPenalty"] intValue];
		}else if([value isEqualTo:[obj valueForKey:@"offWeapon"]]){
			ab=ab+[[obj valueForKey:@"offHandPenalty"] intValue];
		}
	}
	//NSLog(@"3, ab=%d",ab);
	ab=ab+[[obj valueForKey:@"sizeMod"] intValue];
	//NSLog(@"4, ab=%d",ab);
	return ab;
}
+(int)strengthWeaponBonus:(id)value{
	//first get strength value from the character.
	NSManagedObject *obj=[value valueForKey:@"character"];
	int str=[[obj valueForKey:@"strength"] intValue];
	//then convert to bonus.
	str=str-10;
	if(str<0){
		str--;
	}
	str=str/2;
	//check if ranged.
	//NSLog(@"1.2");
	if([[value valueForKey:@"weaponType"] intValue]==2){
		int minStr=[[value valueForKey:@"minStrengthToUse"] intValue];
		minStr=(minStr-10)/2;
		if(minStr>0){
			if(str>minStr){//min str applies and str is bigger than it.
				str=minStr;
			}
		}else if(str>0){//as strength penalty still applies
			str=0;
		}
	}else{//not ranged
		  //1.5 times str bonus for melee when not using a light weapon two handed or optionally to a monster.
		if(str>0 && ![[value valueForKey:@"lightWeapon"] boolValue] && [[value valueForKey:@"weaponType"] intValue]==0 && [[value valueForKey:@"twoHandedWeapon"] boolValue]){
			str=(str*3 +1)/2;
		}
		//if a monster and the attack is secondary, or weapon is off hand, strength bonus is halved.
		if(str>0 && (![[obj valueForKey:@"usesWeapons"] boolValue] && ![[obj valueForKey:@"defaultWeapon"] isEqualTo:value]) || [value isEqualTo:[obj valueForKey:@"offWeapon"]]){
			str=(str+1)/2;
		}
	}
	return str;
}
+(BOOL)isGood:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasSuffix:@"Good"]){
		return YES;
	}
	return NO;
}
+(BOOL)isEvil:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasSuffix:@"Evil"]){
		return YES;
	}
	return NO;
}
+(BOOL)isLawful:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasPrefix:@"Lawful"]){
		return YES;
	}
	return NO;}
+(BOOL)isChaotic:(NSManagedObject *)obj{
	NSString *str=[obj valueForKey:@"alignment"];
	if([str hasPrefix:@"Chaotic"]){
		return YES;
	}
	return NO;
}
+(NSString *)runTestSkill:(NSManagedObject *)skill
					forDC:(int)dc{
	int bonus=[[skill valueForKey:@"total"] intValue];
	return [self runTestWithBonus:bonus
							forDC:dc];
}
+(NSString *)runTestWithBonus:(int)bonus
						forDC:(int)dc{
	int dieRoll=[RandomNumbers randomIntUpTo:20];
	if(dieRoll==1){
		//Fails Automatically
		return @"Critical Failure (rolled 1)";
	}else if(dieRoll==20){
		//Succeeds Automatically
		return @"Success (rolled 20)";
	}else{
		if(dieRoll+bonus>=dc){
			//succeeds
			if(bonus>=0){
				return [[NSString alloc] initWithFormat:@"Success (rolled %d+%d)",dieRoll,bonus];
			}else{
				return [[NSString alloc] initWithFormat:@"Success (rolled %d-%d)",dieRoll,-bonus];
			}
		}else{
			//fails
			if(bonus>=0){
				return [[NSString alloc] initWithFormat:@"Failed (rolled %d+%d)",dieRoll,bonus];
			}else{
				return [[NSString alloc] initWithFormat:@"Failed (rolled %d-%d)",dieRoll,-bonus];
			}
		}
	}
	
}
+(NSString *)getGenderOfCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"gender"] intValue]==0){
		return @"he";
	}else if([[obj valueForKey:@"gender"] intValue]==1){
		return @"she";
	}else{
		return @"it";
	}
}
+(NSString *)getTPSGenderOfCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"gender"] intValue]==0){
		return @"him";
	}else if([[obj valueForKey:@"gender"] intValue]==1){
		return @"her";
	}else{
		return @"it";
	}
}

+(NSString *)getAdjGenderOfCharacter:(NSManagedObject *)obj{
	if([[obj valueForKey:@"gender"] intValue]==0){
		return @"his";
	}else if([[obj valueForKey:@"gender"] intValue]==1){
		return @"her";
	}else{
		return @"their";
	}
}
+(NSString *)updateDefaultWeaponForChar:(NSManagedObject *)obj{
	NSArray *array=[[obj valueForKey:@"weapons"] allObjects];
	if([array count]==0){//no objects in array.
		return @"";
	}
	NSManagedObject *weap=[obj valueForKey:@"defaultWeapon"];
	//check if new weapon is two handed/ranged. (off weapon)
	if([[weap valueForKey:@"twoHandedWeapon"] boolValue] || [[weap valueForKey:@"weaponType"] intValue]!=0){
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"usesTwoWeapons"];
		[obj setValue:nil
			   forKey:@"offWeapon"];
	}
	NSString *defName=[weap valueForKey:@"name"];
	//now check if uses two weapons so name needs to include this weapon.
	if([[obj valueForKey:@"usesTwoWeapons"] boolValue]){
		defName=[[NSString alloc] initWithFormat:@"%@ + %@",defName,[[obj valueForKey:@"offWeapon"] valueForKey:@"name"]];
		[weap setValue:[NSNumber numberWithBool:NO]
				forKey:@"withShield"];
	}
	[self updateShieldBonusForChar:obj
						 forWeapon:weap];
	[obj setValue:defName
		   forKey:@"defaultWeaponForDisp"];
	return defName;
}
+(void)updateShieldBonusForChar:(NSManagedObject *)obj
					  forWeapon:(NSManagedObject *)weap{
	int x=[self dexACBonus:obj];//dex bonus.
	int acTot=[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+x+[[obj valueForKey:@"armourClassDodge"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	int acFlatVal=[[obj valueForKey:@"armourClassArmour"] intValue]+[[obj valueForKey:@"armourClassShield"] intValue]+[[obj valueForKey:@"armourClassDeflection"] intValue]+[[obj valueForKey:@"sizeMod"] intValue]+10;
	if([[weap valueForKey:@"withShield"] boolValue]){
		//enable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:acTot]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:acFlatVal]
			   forKey:@"armourClassFlat"];
	}else{
		//disable shield for AC bonus.
		[obj setValue:[NSNumber numberWithInt:(acTot-[[obj valueForKey:@"armourClassShield"] intValue])]
			   forKey:@"armourClassTotal"];
		[obj setValue:[NSNumber numberWithInt:(acFlatVal-[[obj valueForKey:@"armourClassShield"] intValue])]
			   forKey:@"armourClassFlat"];
	}		
}
+(void)setDefaultWeaponForChar:(NSManagedObject *)obj
					withWeapon:(NSManagedObject *)newWeap{
	NSManagedObject *oldWeap=[obj valueForKey:@"defaultWeapon"];
	[obj setValue:newWeap
		   forKey:@"defaultWeapon"];
	//check if both weapons are the same or the new weapon cannot be used with a second weapon and then switch of two weapon mode.
	if([[obj valueForKey:@"usesTwoWeapons"] boolValue] && ([newWeap isEqualTo:[obj valueForKey:@"offWeapon"]] || [[newWeap valueForKey:@"twoHandedWeapon"] boolValue] || [[newWeap valueForKey:@"weaponType"] intValue]==2)){
		//if light then reduce off weapon penalty as required.
		NSManagedObject *offWeap=[obj valueForKey:@"offWeapon"];
		if([[offWeap valueForKey:@"lightWeapon"] boolValue]){
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
				   forKey:@"offHandPenalty"];
			[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
				   forKey:@"mainHandPenalty"];
		}
		[offWeap setValue:[NSNumber numberWithBool:NO]
				   forKey:@"offWeapon"];
		[obj setValue:nil
			   forKey:@"offWeapon"];
		[obj setValue:[NSNumber numberWithBool:NO]
			   forKey:@"usesTwoWeapons"];
	}
	[oldWeap setValue:nil
			   forKey:@"characterMW"];
	[oldWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"defaultWeapon"];
	[newWeap setValue:[NSNumber numberWithBool:YES]
			   forKey:@"defaultWeapon"];
	//updating weapon stats.
	[newWeap setValue:[NSNumber numberWithInt:[[newWeap valueForKey:@"weaponAttackBonus"] intValue]+[self abilityAttackBonus:newWeap]]
			   forKey:@"attackBonus"];		
	//check shield ac bonus.
	[self updateDefaultWeaponForChar:obj];
}
+(void)setOffHandWeaponForChar:(NSManagedObject *)obj
					withWeapon:(NSManagedObject *)newWeap{
	NSManagedObject *oldWeap=[obj valueForKey:@"offWeapon"];
	[obj setValue:newWeap
		   forKey:@"offWeapon"];
	[obj setValue:[NSNumber numberWithBool:YES]
		   forKey:@"usesTwoWeapons"];
	[oldWeap setValue:nil
			   forKey:@"characterOW"];
	[oldWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"offWeapon"];
	[newWeap setValue:[NSNumber numberWithBool:YES]
			   forKey:@"offWeapon"];
	[newWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"withShield"];
	//check if light weapon, if so, TWOffWeapon gets a +2 bouns.
	if([[newWeap valueForKey:@"lightWeapon"] boolValue] && ![[oldWeap valueForKey:@"lightWeapon"] boolValue]){
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]+2)]
			   forKey:@"offHandPenalty"];
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]+2)]
			   forKey:@"mainHandPenalty"];
	}
	if(![[newWeap valueForKey:@"lightWeapon"] boolValue] && [[oldWeap valueForKey:@"lightWeapon"] boolValue]){
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
			   forKey:@"offHandPenalty"];
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
			   forKey:@"mainHandPenalty"];
	}
	//check shield ac bonus.
	[self updateDefaultWeaponForChar:obj];
}
+(void)cancelOffHandWeaponForChar:(NSManagedObject *)obj{
	NSManagedObject *oldWeap=[obj valueForKey:@"offWeapon"];
	[obj setValue:nil
		   forKey:@"offWeapon"];
	[oldWeap setValue:[NSNumber numberWithBool:NO]
			   forKey:@"offWeapon"];
	[obj setValue:[NSNumber numberWithBool:NO]
		   forKey:@"usesTwoWeapons"];
	//remove light bonus.
	if([[oldWeap valueForKey:@"lightWeapon"] boolValue]){
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"mainHandPenalty"] intValue]-2)]
			   forKey:@"mainHandPenalty"];
		[obj setValue:[NSNumber numberWithInt:([[obj valueForKey:@"offHandPenalty"] intValue]-2)]
			   forKey:@"offHandPenalty"];
	}
	
	//check shield ac bonus.
	[self updateDefaultWeaponForChar:obj];
}
+(void)setLevelOrXPForChar:(NSManagedObject *)obj{
	int lvl=[[obj valueForKey:@"charClassLvl1"] intValue]+[[obj valueForKey:@"charClassLvl2"] intValue]+[[obj valueForKey:@"charClassLvl3"] intValue]+[[obj valueForKey:@"charClassLvlMod"] intValue];	
	int xpForNext=0;
	int i;
	for(i=1;i<=lvl;i++){
		xpForNext=xpForNext+i*1000;
	}
	//now check level isn't too high.
	int cxp=[[obj valueForKey:@"xp"] intValue];
	int lvlFromXp=0;
	while(cxp>-1){
		lvlFromXp++;
		cxp=cxp-lvlFromXp*1000;
	}
	BOOL xpTooLow=NO;
	if(lvlFromXp<lvl){//then the level is too high
		xpTooLow=YES;
	}
	BOOL xpTooHigh=NO;
	if(lvlFromXp>lvl){//a level up is needed.
		xpTooHigh=YES;
	}
	[obj setValue:[NSNumber numberWithInt:lvl]
		   forKey:@"level"];
	[obj setValue:[NSNumber numberWithInt:xpForNext]
		   forKey:@"xpToNextLevel"];
	[obj setValue:[NSNumber numberWithBool:xpTooLow]
		   forKey:@"xpTooLow"];
	[obj setValue:[NSNumber numberWithBool:xpTooHigh]
		   forKey:@"xpTooHigh"];
	int clericLevel=[AbilityChanged turnUndeadCL:obj];
	[obj setValue:[NSNumber numberWithInt:clericLevel]
		   forKey:@"clericLevel"];
	[obj setValue:[NSNumber numberWithInt:([self scoreToBonus:[obj valueForKey:@"charisma"]]+[[obj valueForKey:@"tuHDMiscBonus"] intValue]+clericLevel)]
		   forKey:@"tuHDtotal"];
	[self constitutionChangedForChar:obj];//sets up HP/level.
}
+(NSManagedObject *)findTheCharacterWithMostHPLostInTheArray:(NSArray *)arrayOfChars{
	int difference=0;
	NSManagedObject *objToReturn;
	int i;
	for(i=0;i<[arrayOfChars count];i++){
		NSManagedObject *obj=[arrayOfChars objectAtIndex:i];
		int newDiff=[[obj valueForKey:@"maxHP"] intValue]-[[obj valueForKey:@"currentHP"] intValue];
		if(newDiff>difference){
			objToReturn=obj;
			difference=newDiff;
		}
	}
	return objToReturn;
}
@end
